package com.dbflow5.database;

import java.util.function.Function;

/**
 * Description: Provides a base implementation that wraps a database, so other databaseForTable engines potentially can
 * be used.
 */
public interface DatabaseWrapper {

    /**
     * isInTransaction
     *
     * @return is or not in transaction
     */
    boolean isInTransaction();

    /**
     * The current version of the database.
     *
     * @return version
     */
    int getVersion();

    /**
     * Execute an arbitrary SQL query.
     *
     * @param query sql
     */
    void execSQL(String query);

    /**
     * Begin a transaction.
     */
    void beginTransaction();

    /**
     * Set when a transaction complete successfully to preserve db state.
     */
    void setTransactionSuccessful();

    /**
     * Always called whenever transaction should complete. If [setTransactionSuccessful] is not called,
     * db state will not be preserved.
     */
    void endTransaction();

    /**
     * For a given query, return a [DatabaseStatement].
     *
     * @param rawQuery sql
     * @return DatabaseStatement
     */
    DatabaseStatement compileStatement(String rawQuery);

    /**
     * For a given query and selectionArgs, return a [DatabaseStatement].
     *
     * @param rawQuery sql
     * @param selectionArgs args
     * @return DatabaseStatement
     */
    default DatabaseStatement compileStatement(String rawQuery, String[] selectionArgs){
        DatabaseStatement statement = compileStatement(rawQuery);
        statement.bindAllArgsAsStrings(selectionArgs);
        return statement;
    }

    /**
     * For given query and selection args, return a [FlowCursor] to retrieve data.
     *
     * @param query query
     * @param selectionArgs selectionArgs
     * @return FlowCursor
     */
    FlowCursor rawQuery(String query, String[] selectionArgs);

    FlowCursor query(String tableName, String[] columns, String selection,
              String[] selectionArgs, String groupBy,
              String having, String orderBy);

    int delete(String tableName, String whereClause, String[] whereArgs);

    default void executeTransaction(Function<Void, Void> dbFn) {
        try {
            beginTransaction();
            dbFn.apply(null);
            setTransactionSuccessful();
        } finally {
            endTransaction();
        }
    }
}



